/*
 *    Copyright (c) 2018-2025, proj All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the proj developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: proj
 */
package com.ykht.proj.activity.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codingapi.tx.annotation.TxTransaction;
import com.ykht.proj.activity.Enum.ActivityStatusEnum;
import com.ykht.proj.activity.Enum.CardStatusEnum;
import com.ykht.proj.activity.Enum.PayStatusEnum;
import com.ykht.proj.activity.constant.CardConstant;
import com.ykht.proj.activity.entity.*;
import com.ykht.proj.activity.mapper.VActivityCardMapper;
import com.ykht.proj.activity.mapper.VCardMapper;
import com.ykht.proj.activity.mapper.VOrderMapper;
import com.ykht.proj.activity.mq.producer.ScheduledMsgProducer;
import com.ykht.proj.activity.service.*;
import com.ykht.proj.activity.utils.wx.WxAPIV3AesUtil;
import com.ykht.proj.activity.utils.wx.WxPayProperties;
import com.ykht.proj.activity.utils.wx.WxPayutil;
import com.ykht.proj.activity.vo.*;
import com.ykht.proj.admin.api.feign.RemoteUserService;
import com.ykht.proj.admin.api.vo.UserVO;
import com.ykht.proj.common.core.constant.CommonConstants;
import com.ykht.proj.common.core.constant.SecurityConstants;
import com.ykht.proj.common.core.util.R;
import com.ykht.proj.common.security.util.SecurityUtils;
import com.ykht.proj.coupon.api.feign.RemotePersonService;
import com.ykht.proj.coupon.api.feign.RemoteRewardPersonService;
import com.ykht.proj.coupon.api.feign.RemoteShopService;
import com.ykht.proj.coupon.entity.CnPerson;
import com.ykht.proj.coupon.entity.CnShop;
import com.ykht.proj.coupon.vo.VOrderCardVO;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单(企业 用户购买卡订单)表
 *
 * @author csg
 * @date 2021-05-21 14:22:31
 */
@Service
@Slf4j
public class VOrderServiceImpl extends ServiceImpl<VOrderMapper, VOrder> implements VOrderService {

	static final ThreadLocal<String> sThreadLocal = new InheritableThreadLocal();
	@Resource
	private  VOrderMapper vOrderMapper;
	@Resource
	private  VCardMapper vCardMapper;
	@Autowired
	private  VCardService vCardService;
	@Resource
	private  VActivityCardMapper vActivityCardMapper;
	@Resource
	private  RemotePersonService remotePersonService;
	@Resource
	private  RemoteUserService remoteUserService;
	@Resource
	private  RemoteShopService remoteShopService;
	@Resource
	private  ScheduledMsgProducer scheduledMsgProducer;
	@Resource
	private  VOrderActivityCardService vOrderActivityCardService;
	@Resource
	private  VOrderCardShopService vOrderCardShopService;
	@Autowired
	private  VOrderCardService vOrderCardService;
	@Autowired
	private RemoteRewardPersonService remoteRewardPersonService;

//	public static void main(String[] args) {
////		System.out.println("".length());
////		System.out.println(" ".length());
////		String a = " ";
////		String b = "";
////		System.out.println(StringUtils.isBlank(a));
////		System.out.println(StringUtils.isBlank(b));
////		System.out.println(StringUtils.isEmpty(a));
////		System.out.println(StringUtils.isEmpty(b));
//
//
//		String unsign ="alipay_url=alipay_sdk=alipay-sdk-java-3.4.27.ALL&app_id=2018061460417275&biz_content=%7B%22body%22%3A%22%E6%B5%8B%E8%AF%95%E8%AE%A2%E5%8D%95%22%2C%22extend_params%22%3A%7B%7D%2C%22out_trade_no%22%3A%2211908250000028453790%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22seller_id%22%3A%222088721387102560%22%2C%22subject%22%3A%22%E6%B5%8B%E8%AF%95%E8%AE%A2%E5%8D%95%22%2C%22timeout_express%22%3A%22599m%22%2C%22total_amount%22%3A%220.01%22%7D&charset=utf-8&format=json&method=alipay.trade.app.pay&notify_url=http%3A%2F%2Fapi-test-pcs.snssdk.com%2Fgateway%2Fpayment%2Fcallback%2Falipay%2Fnotify%2Fpay&sign=D2A6ua51os2aIzIH907ppK7Bd9Q2Kk5h7AtKPdudP%2Be%2BNTtAkp0Lfojtgl4BMOIQ3Z7cWyYMx6nk4qbntSx7aZnBhWAcImLbVVr1cmaYAedmrmJG%2B3f8G5TfAZu53ESzUgk02%2FhU1XV0iXRyE8TdEJ97ufmxwsUEc7K0EvwEFDIBCJg73meQtyCRFgCqYRWvmxetQgL7pwfKXpFXjAYsvFrRBas2YGYt689XpBS321g%2BZ8SZ0JOtLPWqhROzEs3dnAtWBW15y3NzRiSNi5rPzah4cWd4SgT0LZHmNf3eDQEHEcPmofoWfnA4ao75JmP95aLUxerMumzo9OwqhiYOUw%3D%3D&sign_type=RSA2&timestamp=2019-08-25+16%3A11%3A22&version=1.0&app_id=800000040005&body=microapp test&currency=CNY&merchant_id=1300000004&notify_url=https://tp-pay.snssdk.com/cashdesk/test/paycallback&out_order_no=MicroApp7075638135&payment_type=direct&product_code=pay&sign_type=MD5&subject=microapp test&timestamp=1566720681&total_amount=1&trade_time=1566720681&trade_type=H5&uid=2019012211&valid_time=300&version=2.0&wx_type=MWEB&wx_url=https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx25161122572189727ea14cfd1832451500&package=2746219290";
//
//		String sign1 = DigestUtil.md5Hex(unsign+"a");
//		System.out.println(sign1);
//
//	}
	/**
	 * 下单
	 * @param cardId
	 * @param shopIds
	 * @param shareId
	 * @return
	 */
	@Override
	@TxTransaction(isStart = true ) // 请求方 要加 isStart = true  被请求的不用加  isStart = true  控制事物 注解
	@Transactional(rollbackFor = Exception.class)
	public R order(Long cardId, String shopIds, Long shareId) {
		List<Long> ids = StringUtils.isBlank(shopIds)?new ArrayList():Arrays.stream(shopIds.split(",")).map(Long::parseLong).collect(Collectors.toList());
		//校验
		Integer status = this.checkBase(cardId,ids);
		if (status!=CardConstant.CAN_BUY_OK) return R.failed();
		//下单
		VOrderCard orderCard = this.createOrder(cardId,ids,shareId);
		//分销佣金
		remoteRewardPersonService.rewardByShareCard(BeanUtil.toBean(orderCard, VOrderCardVO.class));
		//后续操作
		this.orderNext(orderCard);
		return R.ok(orderCard.getOrderId());

	}

	@Override
	public Integer checkBase(Long cardId, List<Long> ids) {
		Long loginId = SecurityUtils.getPersonId();
		R<CnPerson> r = remotePersonService.getPersonById(loginId);

		CnPerson person = r.getData();
		log.info("--->校验手机号");
		if (null==person.getPhone()) throw new RuntimeException("用户未授权手机号");
		sThreadLocal.set(person.getPhone());

		VCard card = new VCard().selectById(cardId);
		log.info("--->校验卡是否存在");
		if (card == null) throw new RuntimeException("卡不存在");
		if (card.getCardStatus()!= CardStatusEnum.AT_WORK.getValue()) throw new RuntimeException("此卡"+CardStatusEnum.getDescByVal(card.getCardStatus()));

		log.info("--->校验选择的商家数量");
		if (card.getDiscountType() == CardConstant.DISCOUNT_TYPE_BF && card.getDiscountNumber() != ids.size()) throw new RuntimeException(String.format("应当选择%s个商家，实际选择了%s个商家", card.getDiscountNumber(), ids.size()));

		return this.checkCanBuy(cardId,null);
	}


	/**
	 * 0可买1已售罄2购买次数用完
	 * check可否购买
	 * @return
	 */
	@Override
	public Integer checkCanBuy(Long cardId,Long orderId) {
		log.info("检查卡id：{}是否可购买",cardId);

		VCard card = new VCard().selectById(cardId);
		//卡已售完或下架
		if (card.getCardStatus()!=CardStatusEnum.AT_WORK.getValue()) {
			log.info("卡不在上架中");
			return CardConstant.CAN_BUY_EXPIRE;
		}

		VActivityCard activityCard = new VActivityCard().selectOne(Wrappers.lambdaQuery(VActivityCard.class).eq(VActivityCard::getCardId,cardId).eq(VActivityCard::getStatus, ActivityStatusEnum.AT_WORK.getValue()));

		//当前没有活动，可以购买
		if (activityCard != null){
			VActivity vActivity = new VActivity().selectOne(Wrappers.lambdaQuery(VActivity.class).eq(VActivity::getId,activityCard.getActivityId()).eq(VActivity::getStatus,0));
//		if (vActivity==null) return true;
			//活动库存不够
			if (activityCard.getActivityStock()-activityCard.getSaleVolume()-activityCard.getFrozenVolume()<=0) {
				if (null != orderId){

				}else {
					log.info("活动库存不够");
					return CardConstant.CAN_BUY_STOCK_EMPTY;
				}
			}
			//活动不限购买次数
			if (vActivity.getPurchaseType()==0) return CardConstant.CAN_BUY_OK;
			//通过此活动已购买的数量
			Integer num = new VOrderCard().selectCount(Wrappers.lambdaQuery(VOrderCard.class)
					.eq(VOrderCard::getPersonId, SecurityUtils.getPersonId())
					.eq(VOrderCard::getActivityId,vActivity.getId())
					.eq(VOrderCard::getCardId,cardId).ne(null != orderId,VOrderCard::getOrderId,orderId)
					.in(VOrderCard::getPayStatus, PayStatusEnum.NOT_PAY.getValue(),PayStatusEnum.PAY.getValue()));//待支付和已支付
			if (vActivity.getPurchaseNumber()<=num){
				log.info("通过此活动已购买的数量{},活动限制购买的数量{}",num,vActivity.getPurchaseNumber());
				return CardConstant.CAN_BUY_TIMES_EMPTY;
			}
		}else {
			if (card.getStockNumber()-card.getSaleVolume()-card.getFrozenVolume()<=0) {
				log.info("卡已售完");
				return CardConstant.CAN_BUY_STOCK_EMPTY;
			}
		}


		return CardConstant.CAN_BUY_OK;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public VOrderCard createOrder(Long cardId, List<Long> ids, Long shareId) {

		//卡表减库存
		log.info("->减库存");
		VCard card = new VCard().selectById(cardId);

		//订单表
		VOrder order = new VOrder();
		//订单号
		String orderCode = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+ RandomUtil.randomNumbers(4);
		order.setOrderCode(orderCode);
		order.setPersonId(SecurityUtils.getPersonId());
		order.setCustomerType(CardConstant.CUSTOMER_TYPE_PERSON);
		order.setPurchaseNum(1);
		order.setCopeAmount(card.getPrice());
		order.setPayStatus(PayStatusEnum.NOT_PAY.getValue());
		order.setCreateTime(LocalDateTime.now());
		order.setCreateUser(SecurityUtils.getPersonId());
		order.setPhone(String.valueOf(sThreadLocal.get()));
		order.setPurchaseType(CardConstant.PURCHASE_TYPE_XCX);
		order.setShareId(shareId);

		//订单卡表
		VOrderCard orderCard = new VOrderCard();
		orderCard.setOrderCode(orderCode);
		orderCard.setPersonId(SecurityUtils.getPersonId());
//		orderCard.setEnterpriseId(null);
		orderCard.setCustomerType(CardConstant.CUSTOMER_TYPE_PERSON);//客戶类型：0个人  1企业
		orderCard.setPurchaseType(CardConstant.PURCHASE_TYPE_XCX);//购买类型（订单来源）： 0小程序  1代客下单
		orderCard.setPayStatus(PayStatusEnum.NOT_PAY.getValue());//支付状态 0 待支付 1已完成  2已过期3已取消
		orderCard.setCardId(cardId);
		orderCard.setCardType(CardConstant.CARD_TYPE_PTK);//卡类型：0普通卡（展示卡本身外貌）   1联名卡（展示企业自己设置的外貌
		orderCard.setCardName(card.getName());
		orderCard.setCardImg(card.getBackImg());
		orderCard.setPersonId(SecurityUtils.getPersonId());
		orderCard.setPersonPhone(String.valueOf(sThreadLocal.get()));
		orderCard.setCreateTime(LocalDateTime.now());
		orderCard.setCreateUser(SecurityUtils.getPersonId());
		orderCard.setCardStatus(CardConstant.CARD_STATUS_WDH);
		orderCard.setShareId(shareId);

		orderCard.setCardPrice(card.getPrice());
		orderCard.setCardActualPrice(card.getPrice());
		orderCard.setCardReducePrice(BigDecimal.ZERO);
		order.setCopeAmount(card.getPrice());
		order.setPayAmount(card.getPrice());
		order.setDiscountAmount(BigDecimal.ZERO);

		//查看当前卡是否存在活动
		VActivityCard activityCard = new VActivityCard().selectOne(Wrappers.lambdaQuery(VActivityCard.class).eq(VActivityCard::getCardId,cardId).eq(VActivityCard::getStatus, ActivityStatusEnum.AT_WORK.getValue()));
		if (activityCard!=null){
			VActivity tempActivity =  new VActivity().selectById(activityCard.getActivityId());
			//活动快照
			VOrderActivity orderActivity = BeanUtil.toBean(tempActivity,VOrderActivity.class);
			orderActivity.setId(null);
			orderActivity.setActivityId(tempActivity.getId());
			orderActivity.setTenantId(null);
			orderActivity.setCreateTime(LocalDateTime.now());
			orderActivity.setCreateUser(SecurityUtils.getPersonId());
			orderActivity.insert();

			//活动关联卡快照
			List<VActivityCard> activityCardList = new VActivityCard().selectList(Wrappers.lambdaQuery(VActivityCard.class).eq(VActivityCard::getActivityId,tempActivity.getId()));
			List<VOrderActivityCard> orderActivityCardList = activityCardList.stream().map(o->{
				VOrderActivityCard orderActivityCard = new VOrderActivityCard();
				orderActivityCard.setOrderActivityId(tempActivity.getId());
				orderActivityCard.setCreateTime(LocalDateTime.now());
				orderActivityCard.setCreateUser(SecurityUtils.getPersonId());
				orderActivityCard.setTenantId(null);
				return orderActivityCard;
			}).collect(Collectors.toList());
			vOrderActivityCardService.saveBatch(orderActivityCardList);

			//订单相关
			order.setActivityId(activityCard.getActivityId());
			order.setOrderActivityId(orderActivity.getId());
			//订单卡相关
			orderCard.setActivityId(activityCard.getActivityId());
			orderCard.setOrderActivityId(orderActivity.getId());

			orderCard.setCardPrice(card.getPrice());
			orderCard.setCardActualPrice(activityCard.getActivityPrice());
			orderCard.setCardReducePrice(card.getPrice().subtract(activityCard.getActivityPrice()));
			order.setCopeAmount(card.getPrice());
			order.setPayAmount(activityCard.getActivityPrice());
			order.setDiscountAmount(card.getPrice().subtract(activityCard.getActivityPrice()));
		}
		order.insertOrUpdate();

		orderCard.setOrderId(order.getId());
		orderCard.insertOrUpdate();

		//库存是分开的
		//释放活动库存，库存加一
		if (orderCard.getActivityId()!=null){
			vActivityCardMapper.updateSalesVolume(0,1,orderCard.getActivityId(),orderCard.getCardId());
			log.info("***********************************冻结活动卡库存**********************************************");
		}else {
			vCardMapper.updateSalesVolume(0,0,0,1,orderCard.getCardId());
			log.info("***********************************冻结卡库存**********************************************");
		}

		//c端用户选择门店表
		//优惠类型  0全部享用  1部分享用
		if (CardConstant.DISCOUNT_TYPE_BF==card.getDiscountType()&&ids.size()>0){
			String[] idss = ids.stream().map(o->String.valueOf(o)).collect(Collectors.toList()).toArray(new String[ids.size()]);
			List<CnShop> shopList = remoteShopService.getByIds(idss);
			List<VOrderCardShop > orderCardShopList = ids.stream().map(o->{
				VOrderCardShop vOrderCardShop = new VOrderCardShop();
				vOrderCardShop.setActivityId(orderCard.getActivityId());
				vOrderCardShop.setCardId(orderCard.getCardId());
				vOrderCardShop.setShopId(o);
				shopList.stream().filter(oo->oo.getId().equals(o)).findFirst().ifPresent(oo->{
					vOrderCardShop.setBrandId(oo.getBrandId());
					vOrderCardShop.setCompanyId(oo.getCompanyId());
				});
				vOrderCardShop.setCreateUser(SecurityUtils.getPersonId());
				vOrderCardShop.setCreateTime(LocalDateTime.now());
				vOrderCardShop.setOrderCardId(orderCard.getId());
				vOrderCardShop.setPersonId(SecurityUtils.getPersonId());
				vOrderCardShop.setPurchaseType(0);
				vOrderCardShop.setCurrentStatus(0);
				return vOrderCardShop;
			}).collect(Collectors.toList());
			vOrderCardShopService.saveBatch(orderCardShopList);
		}
		return orderCard;
	}


	@Override
	public void orderNext(VOrderCard orderCard) {
		log.info("->生产者发送消息");
		// 设置延时等级16,这个消息将在30分钟之后发送(现在只支持固定的几个时间,详看delayTimeLevel)1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
		scheduledMsgProducer.sendOrderScheduledMsg(orderCard.getId().toString(),16);
	}

	/**
	 * 订单过期
	 * @param orderCardId
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void expireOrder(Long orderCardId) {
		//订单卡修改状态
		VOrderCard orderCard = new VOrderCard().selectById(orderCardId);
		//订单修改状态
		VOrder order = new VOrder().selectById(orderCard.getOrderId());
		boolean oederNum = order.update(Wrappers.lambdaUpdate(VOrder.class).set(VOrder::getPayStatus,PayStatusEnum.BE_OVERDUE.getValue()).eq(VOrder::getId,orderCard.getOrderId()).eq(VOrder::getPayStatus,PayStatusEnum.NOT_PAY.getValue()));
		boolean orderCardNum = orderCard.update(Wrappers.lambdaUpdate(VOrderCard.class).set(VOrderCard::getPayStatus,PayStatusEnum.BE_OVERDUE.getValue()).eq(VOrderCard::getId,orderCardId).eq(VOrderCard::getPayStatus,PayStatusEnum.NOT_PAY.getValue()));
		//库存是分开的
		//释放活动库存，库存加一
		if (orderCardNum&&orderCard.getActivityId()!=null){
			vActivityCardMapper.updateSalesVolume(0,-1,orderCard.getActivityId(),orderCard.getCardId());
			log.info("***********************************解冻活动卡库存**********************************************");
		}else if(oederNum){
			//释放卡库存，库存加一
			vCardMapper.updateSalesVolume(0,0,0,-1,orderCard.getCardId());
			log.info("***********************************解冻卡库存**********************************************");
		}
	}

	@Resource
	private WxPayProperties wxPayProperties;

	@Override
	public R pay(Long orderId) {
		try {
			log.info("->验证用户");
			R<CnPerson> r = remotePersonService.getPersonById(SecurityUtils.getPersonId());
			if (CommonConstants.SUCCESS!=r.getCode()) return R.failed("用户异常");
			CnPerson person = r.getData();
			if (null==person.getPhone()) return R.failed("用户未授权手机号");
			if (0!=person.getStatus()) return R.failed("用户状态异常");

			VOrder order = this.getById(orderId);
			VOrderCard vOrderCard = new VOrderCard().selectOne(Wrappers.lambdaQuery(VOrderCard.class).eq(VOrderCard::getOrderId,order.getId()));
			//检查是否可下单
			Integer  status = this.checkCanBuy(vOrderCard.getCardId(),orderId);
			if (status!=CardConstant.CAN_BUY_OK)  return R.failed(status);
			//统一下单
			log.info("->统一下单");
			String result = WxPayutil.v3PayTransactionsJsapi_V2(wxPayProperties,person,order);
			JSONObject resultJson = JSONUtil.parseObj(result);
			String prepay_id = resultJson.getStr("prepay_id");
			if(prepay_id==null||"null".equals(prepay_id)) return R.failed("下单失败");
			log.info("->构建小程序调起支付的参数");
			JSONObject data = WxPayutil.toSign(wxPayProperties,prepay_id);
			return R.ok(data,"下单成功");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return R.failed("下单失败");
		}

	}

	@Override
	@TxTransaction(isStart = true)
	@Transactional(rollbackFor = Exception.class)
	@SneakyThrows
	public R toCallback(String data, HttpServletRequest request) {
		log.info("————————————————————————————————->对返回的数据进行验签");

		log.info("—————————————————————————————————->验签成功，解析回调数据：{}",data);
		JSONObject jsonData =JSONUtil.parseObj(data);
		JSONObject resource = jsonData.getJSONObject("resource");
		String nonce = resource.getStr("nonce");//加密使用的随机串示例值：fdasflkja484w
		String ciphertext = resource.getStr("ciphertext");//Base64编码后的开启/停用结果数据密文示例值：sadsadsadsad
		String associated_data = resource.getStr("associated_data");//附加数据示例值：fdasfwqewlkja484w
//			String algorithm = resource.getStr("algorithm");//对开启结果数据进行加密的加密算法，目前只支持AEAD_AES_256_GCM

		//解密回调信息
		byte[] key = wxPayProperties.getApiv3privateKey().getBytes("UTF-8");
		WxAPIV3AesUtil aesUtil = new WxAPIV3AesUtil(key);
		String ciphert = aesUtil.decryptToString(associated_data.getBytes("UTF-8"),nonce.getBytes("UTF-8"),ciphertext);

		log.info("->解密后的数据：{}",ciphert);
		//解析返回的数据
		JSONObject ciphertJ = JSONUtil.parseObj(ciphert);
//			String appid = ciphertJ.getStr("appid");//直连商户申请的公众号或移动应用appid
//			String mchid = ciphertJ.getStr("mchid");//商户的商户号，由微信支付生成并下发。示例值：1230000109
		String out_trade_no = ciphertJ.getStr("out_trade_no");//商户订单号
		String transaction_id = ciphertJ.getStr("transaction_id");//微信支付订单号
//			String trade_type = ciphertJ.getStr("trade_type");//交易类型
		String trade_state = ciphertJ.getStr("trade_state");//交易状态:交易状态，枚举值：SUCCESS：支付成功 REFUND：转入退款 NOTPAY：未支付 CLOSED：已关闭 REVOKED：已撤销（付款码支付）USERPAYING：用户支付中（付款码支付）PAYERROR：支付失败(其他原因，如银行返回失败)
		String trade_state_desc = ciphertJ.getStr("trade_state_desc");//交易状态描述
		log.info("支付状态：{}",trade_state);
		log.info("支付状态描述：{}",trade_state_desc);
		if(!"SUCCESS".equals(trade_state)) {
			return R.failed();
		}

		String success_time = ciphertJ.getStr("success_time");//支付完成时间
		JSONObject payer= ciphertJ.getJSONObject("payer");//支付者
		JSONObject amount= ciphertJ.getJSONObject("amount");//订单金额
		int payer_total = amount.getInt("payer_total");//用户支付金额

		log.info("->处理out_trade_no:{}订单业务{}",out_trade_no,payer_total);

		VOrder order = this.getOne(Wrappers.lambdaQuery(VOrder.class).eq(VOrder::getOrderCode,out_trade_no));
		//c端的只会返回一条
		VOrderCard orderCard = new VOrderCard().selectOne(Wrappers.lambdaQuery(VOrderCard.class).eq(VOrderCard::getOrderCode,out_trade_no));

		if (PayStatusEnum.PAY.getValue()==order.getPayStatus()) return R.ok();
		/*int payTotal = order.getPayAmount().multiply(new BigDecimal(100)).intValue();
		if (payTotal!=payer_total){
			log.error("本服务订单金额{}分，微信返回{}分，不一致",payTotal,payer_total);
			return R.failed();
		}*/
		if (PayStatusEnum.PAY.getValue()==order.getPayStatus()
				&&null!=order.getPayAmount()
				&&null!=order.getPayTime()) return  R.ok("支付成功");
		if (PayStatusEnum.BE_OVERDUE.getValue()==order.getPayStatus()) return  R.failed("订单已过期");

		log.info("--->查看是否需要返佣：");
		VCard card = new VCard().selectById(orderCard.getCardId());
		BigDecimal percentage = BigDecimal.ZERO;
		if (card != null && card.getFxFlag() != null && card.getFxFlag()==1) {//0不参与1参与
			percentage = card.getReturnPercentage();
			if (percentage== null){
				percentage = BigDecimal.ZERO;
			}
		}

		log.info("--->修改订单数据");

		//更新订单表
//		order.setPayAmount(new BigDecimal(payer_total).divide(new BigDecimal(100)));
//		if (orderCard.getActivityId()!=null){
//			order.setDiscountAmount(order.getCopeAmount().subtract(BigDecimal.valueOf(payer_total*100)));
//		}
		order.setPayType(0);
		order.setPayTime(LocalDateTime.parse(success_time,DateTimeFormatter.ISO_DATE_TIME));
		order.setPayStatus(PayStatusEnum.PAY.getValue());
		order.setTransactionId(transaction_id);
		order.setReturnMoney(order.getPayAmount().multiply(percentage));
		order.updateById();
		//更新订单卡表
		orderCard.setTransactionId(transaction_id);
		orderCard.setPayType(0);
		orderCard.setPayStatus(PayStatusEnum.PAY.getValue());
		orderCard.setPayTime(LocalDateTime.parse(success_time,DateTimeFormatter.ISO_DATE_TIME));
		orderCard.setCardStatus(CardConstant.CARD_STATUS_YJH);
		orderCard.setReturnMoney(order.getPayAmount().multiply(percentage));
		orderCard.updateById();


		//更新开卡数量
		if (orderCard.getActivityId()!=null){
			vActivityCardMapper.updateSalesVolume(1,-1,orderCard.getActivityId(),orderCard.getCardId());
			vCardMapper.updateSalesVolume(0,1,1,0,orderCard.getCardId());
			log.info("***********************************解冻活动卡库存**********************************************");
		}else {
			vCardMapper.updateSalesVolume(1,0,1,-1,orderCard.getCardId());
			log.info("***********************************解冻卡库存**********************************************");
		}

		//添加会员表
		VInfo info = new VInfo();
		info.setCType(card.getType());
		info.setActivityId(orderCard.getActivityId());
		info.setCardId(orderCard.getCardId());
		info.setOrderCardId(orderCard.getId());
		info.setPersonId(orderCard.getPersonId());
		info.setStatus(0);
		info.setOrderId(orderCard.getOrderId());
		info.setOpenCardTime(LocalDateTime.now());
		String vipAccount = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+RandomUtil.randomNumbers(4);
		info.setVipAccount(vipAccount);//卡号
		String useCode = String.valueOf(System.currentTimeMillis()).substring(5, 13);
		info.setUseCode(useCode);//核销码
		info.setTotalActMoney(BigDecimal.ZERO);//累计消费金额
		info.setTotalMoney(BigDecimal.ZERO);//累计实付金额
		//使用有效类型: 0自开卡之日起X天有效  1时间范围  2 无期限
		System.out.println(card);
		switch (card.getUseEffectiveType()){
			case 0:
				info.setStartTime(LocalDateTime.now());
				if (card.getEffectiveDays()!=null){
					info.setEndTime(LocalDateTime.of(LocalDateTime.now().toLocalDate(), LocalTime.MAX.withNano(0)).plusDays(card.getEffectiveDays()-1));
				}
				break;
			case 1:
				info.setStartTime(card.getStaTime());
				info.setEndTime(card.getEndTime());
				break;
			case 2:
				info.setStartTime(LocalDateTime.now());
				info.setEndTime(card.getEndTime());
				break;
		}

		info.setCreateTime(LocalDateTime.now());
		info.setCreateUser(orderCard.getPersonId());
		info.insert();
		log.info("{}",info);
		//分销结算给佣金
		remoteRewardPersonService.rewardCard(BeanUtil.toBean(orderCard,VOrderCardVO.class), SecurityConstants.FROM_IN);
		return R.ok();
	}

//	public static void main(String[] args) {
//		BigDecimal decimal = null;
//		BigDecimal decimal1 = BigDecimal.ZERO;
//		System.out.println(BigDecimal.valueOf(2).multiply(BigDecimal.ZERO));
//		System.out.println(decimal.multiply(decimal1));
//	}
	/**
	 * 获取 活动列表字段 付款人数
	 *
	 * @param longList
	 * @return
	 */
	@Override
	public List<VActivityVo> getPurchaseCount(List<Long> longList) {
		return vOrderMapper.getPurchaseCount(longList);
	}

	/**
	 * 企业购买卡（代客下单）
	 *
	 * @param entOrderReq
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public R addEntBuyCard(EntOrderReq entOrderReq) {
		log.info("->添加企业购买订单表");
		Long userId = SecurityUtils.getUserId();
		String orderCode = DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomStringUtils.random(6, "0123456789");
		entOrderReq.setCreateUser(userId);
		entOrderReq.setCreateTime(LocalDateTime.now());
		entOrderReq.setPayTime(LocalDateTime.now());
		entOrderReq.setOrderCode(orderCode);
		entOrderReq.setCustomerType(CardConstant.CUSTOMER_TYPE_ENT);
		entOrderReq.setPurchaseType(CardConstant.PURCHASE_TYPE_DKXD);
		entOrderReq.setPayStatus(PayStatusEnum.PAY.getValue());
		VEnt ent = new VEnt().selectById(entOrderReq.getEnterpriseId());
		entOrderReq.setPhone(ent.getPhone());
		VOrder vOrder = BeanUtil.toBean(entOrderReq, VOrder.class);
		this.save(vOrder);
		log.info("->添加企业购买订单和卡的关联表");
		List<VOrderCard> orderCardList = new ArrayList<>();
		List<VCard> cardList = new ArrayList<>();
		// 总价格实际支付
		BigDecimal payAmountCount = BigDecimal.ZERO;

		//  (总卡-1) 的总价格优惠
		BigDecimal cardSTotalDiscount = BigDecimal.ZERO;
		// 卡数量自增
		Integer addition = 0;
		// (总卡-1)  卡数量
		Integer entOrderCardReqList = entOrderReq.getEntOrderCardReqList().size();
		for (EntOrderCardReq req : entOrderReq.getEntOrderCardReqList()) {
			addition++;
			// 单卡原价总价格  =  单卡原价  *  单卡数量
			BigDecimal cardTotalPrice = req.getCardPrice().multiply(BigDecimal.valueOf(req.getBuyCount())).setScale(2, BigDecimal.ROUND_HALF_UP);
			// 单卡总优惠   =  单张卡原价总价格 / 全卡总应付 * 全卡总优惠
			BigDecimal cardTotalDiscount = cardTotalPrice.divide(entOrderReq.getCopeAmount(),2, BigDecimal.ROUND_HALF_UP).multiply(entOrderReq.getDiscountAmount());
			if (entOrderCardReqList.equals(addition)){
				cardTotalDiscount = entOrderReq.getDiscountAmount().subtract(cardSTotalDiscount);
			}
			cardSTotalDiscount = cardSTotalDiscount.add(cardTotalDiscount);
			// 单张卡优惠 = 单卡总优惠 /  单卡数量
			BigDecimal TotalDiscount = cardTotalDiscount.divide(BigDecimal.valueOf(req.getBuyCount()),2, BigDecimal.ROUND_HALF_UP);

			req.setCardReducePrice(TotalDiscount.compareTo(new BigDecimal("0.01")) == 1 ? TotalDiscount : BigDecimal.ZERO);
			req.setCardActualPrice(req.getCardPrice().subtract(TotalDiscount).compareTo(new BigDecimal("0.01")) == 1
					? req.getCardPrice().subtract(TotalDiscount) : BigDecimal.ZERO);
			req.setCreateUser(userId);
			req.setCreateTime(LocalDateTime.now());
			req.setOrderId(vOrder.getId());
			req.setCardStatus(CardConstant.CARD_STATUS_WDH);
			req.setEnterpriseId(vOrder.getEnterpriseId());
			req.setCustomerType(CardConstant.CUSTOMER_TYPE_ENT);
			req.setPurchaseType(CardConstant.PURCHASE_TYPE_DKXD);
			req.setPayType(vOrder.getPayType());
			req.setPayStatus(1);
			req.setPayTime(vOrder.getPayTime());
			req.setTransactionId(vOrder.getTransactionId());
			VCard vCard = new VCard();
			vCard.setId(req.getCardId());
			vCard.setSaleVolume(req.getBuyCount());
			vCard.setStockNumber(req.getBuyCount());
			cardList.add(vCard);
			//  最后张卡的金额
			Integer buyCount = req.getBuyCount() - 1;
			for (int i = 0; i < req.getBuyCount(); i++) {
				req.setRedeemCode(RandomStringUtils.randomAlphanumeric(16).toLowerCase());
				req.setOrderCode(orderCode);
				if (buyCount.equals(i)){
					// 单张卡实际支付 = 单卡原价总价格 -  单卡总优惠
					BigDecimal subtract2 = cardTotalPrice.subtract(cardTotalDiscount);
					//
//					TotalDiscount.
					// 优惠了多少金额
					BigDecimal subtract = cardTotalDiscount.subtract(TotalDiscount.multiply(BigDecimal.valueOf(buyCount))).setScale(2, BigDecimal.ROUND_DOWN);;
					//
//					discountAmountCount = discountAmountCount.add()
					req.setCardReducePrice(subtract.compareTo(new BigDecimal("0.01")) == 1 ? subtract : BigDecimal.ZERO);
					// 实际支付价格
					BigDecimal subtract1 = req.getCardPrice().subtract(cardTotalDiscount.subtract(TotalDiscount.multiply(BigDecimal.valueOf(buyCount)))).setScale(2, BigDecimal.ROUND_DOWN);;
					req.setCardActualPrice(subtract.compareTo(new BigDecimal("0.01")) == 1 ? subtract1 : BigDecimal.ZERO);
					// 大循环最后一次
					if (entOrderCardReqList.equals(addition)){
						// 实际支付价格
						BigDecimal decimal = entOrderReq.getPayAmount().subtract(payAmountCount);
						req.setCardActualPrice(decimal);
						// 优惠了多少金额
						req.setCardReducePrice(req.getCardPrice().subtract(decimal));
					}
				}
				// 相减加卡实际支付
				payAmountCount = payAmountCount.add(req.getCardActualPrice());
				req.setTenantId(null);
				orderCardList.add(BeanUtil.toBean(req, VOrderCard.class));
			}
		}
		vOrderCardService.saveBatch(orderCardList);
		vCardService.updateBatch(cardList);
		return R.ok();
	}


	@Override
	public R getVOrderPage(Page<VOrder> page, VOrderPageReq req) {
		page = new VOrder().selectPage(page,Wrappers.lambdaQuery(VOrder.class)
				.ge(req.getStartTime()!=null,VOrder::getCreateTime,req.getStartTime())
				.le(req.getEndTime()!=null,VOrder::getCreateTime,req.getEndTime())
				.eq(req.getPhone()!=null,VOrder::getPhone,req.getPhone())
				.orderByDesc(VOrder::getCreateTime));
		Page<VOrderPageResp> tempPage = new Page<>();
		tempPage.setPages(page.getPages());
		tempPage.setTotal(page.getTotal());
		tempPage.setSize(page.getSize());
		tempPage.setCurrent(page.getCurrent());
		List<String> perIds = new ArrayList<>();
		List<Long> entIds = new ArrayList<>();
		List<VOrderPageResp> list = page.getRecords().stream().map(o->{
			VOrderPageResp resp = BeanUtil.toBean(o,VOrderPageResp.class);
			if (0==o.getCustomerType()) perIds.add(o.getPersonId().toString());
			if (1==o.getCustomerType()) entIds.add(o.getEnterpriseId());
			return resp;
		}).collect(Collectors.toList());
		tempPage.setRecords(list);
		R<List<CnPerson>> r = remotePersonService.getPersonByIds(String.join(",",perIds));
		List<CnPerson> personList = r.getData();
		List<VEnt> entList = new ArrayList<>();
		if (entIds.size()>0){
			 entList = new VEnt().selectList(Wrappers.lambdaQuery(VEnt.class).in(VEnt::getId,entIds));
		}
		List<VEnt> finalEntList = entList;
		tempPage.getRecords().stream().forEach(o->{
			if (0==o.getCustomerType()){
				personList.stream().filter(oo->oo.getId().equals(o.getPersonId())).findFirst().ifPresent(ooo->{
					o.setName(ooo.getNickName());
				});
			}else if (1==o.getCustomerType()){
				finalEntList.stream().filter(oo->oo.getId().equals(o.getEnterpriseId())).findFirst().ifPresent(ooo->{
					o.setName(ooo.getName());
				});
			}
		});

		return R.ok(tempPage);
	}

	@Override
	public R<GetVOrderVO> getVOrderVO(Long orderId) {
		GetVOrderVO vo = new GetVOrderVO();
		VOrder order = new VOrder().selectById(orderId);
		VOrderPageResp resp = BeanUtil.toBean(order,VOrderPageResp.class);
		switch (order.getCustomerType()){
			case 0:
				R<CnPerson> r = remotePersonService.getPersonById(order.getPersonId());
				if (r.getCode()==CommonConstants.SUCCESS){
					CnPerson person = r.getData();
					resp.setName(person.getNickName());
					resp.setCreateName(person.getNickName());
				}
				break;
			case 1:
				VEnt ent = new VEnt().selectById(order.getEnterpriseId());
				resp.setName(ent.getName());
				UserVO userVO =  remoteUserService.getByIdUser(order.getCreateUser());
				if (userVO!=null){
					resp.setCreateName(userVO.getUsername());
				}
				break;
		}
		if (order.getReturnMoney()!=null || order.getReturnMoney().compareTo(BigDecimal.ZERO)!=0){
			R<CnPerson> r = remotePersonService.getPersonById(order.getShareId());
			CnPerson person = r.getData();
			if (person!=null){
				resp.setShareName(person.getNickName());
				resp.setPhone(person.getPhone());
			}
		}
		vo.setOrder(resp);
		List<OrderGroup> list = vOrderCardService.orderGroup(orderId);
		vo.setList(list);
		return R.ok(vo);
	}

	/**
	 * 企业购买卡记录 分页查询
	 *
	 * @param page     分页
	 * @param entOrderDto 条件
	 * @return
	 */
	@Override
	public IPage<EntOrderDto> getEntBuyCardListPage(Page page, EntOrderDto entOrderDto) {
		return vOrderMapper.getEntBuyCardListPage(page, entOrderDto);
	}
}
